﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using LuaInterface;
using UObject = UnityEngine.Object;
using UnityEngine.U2D;
using UnityEngine.UI;
using SimpleJSON;
using UnityEngine.Networking;
using Spine.Unity;
using UnityEngine.Serialization;

public class AssetBundleInfo
{
    public readonly AssetBundle MAssetBundle;
    public int MReferencedCount;

    public AssetBundleInfo(AssetBundle assetBundle)
    {
        MAssetBundle = assetBundle;
        MReferencedCount = 0;
    }
}

namespace YanhuaMMO
{
    public class CacheObject
    {
        public float lastRefTime = Time.realtimeSinceStartup;
        public int refCount = 0;
    }

    public class ResourceManager : Manager
    {
        [SerializeField] private string mBaseDownloadingUrl = "";
        private string[] _mAllManifest = { "update/updategame.unity3d" };
        [SerializeField] private AssetBundleManifest mAssetBundleManifest = null;
        private readonly Dictionary<string, string[]> _mDependencies = new Dictionary<string, string[]>();
        private readonly Dictionary<string, AssetBundleInfo> _mLoadedAssetBundles = new Dictionary<string, AssetBundleInfo>();
        private readonly Dictionary<string, AssetBundleInfo> _mLoadedAssetBundlesAsync = new Dictionary<string, AssetBundleInfo>();
        private readonly Dictionary<string, List<LoadAssetRequest>> _mLoadRequests = new Dictionary<string, List<LoadAssetRequest>>();
        private readonly Dictionary<string, AssetBundleCreateRequest> _mLoadAsyncRequests = new Dictionary<string, AssetBundleCreateRequest>();
        private readonly Dictionary<string, int> _mLoadAsyncRequestCount = new Dictionary<string, int>();
        private Dictionary<string, Sprite> _dSprite = new Dictionary<string, Sprite>();

        public static Dictionary<string, SpriteAtlas> SLoadedSpriteAtlas = new Dictionary<string, SpriteAtlas>();
        public static Dictionary<string, Sprite> SLoadedSprites = new Dictionary<string, Sprite>();
        public static Dictionary<string, GameObject> SLoadedPrefabs = new Dictionary<string, GameObject>();
        public static Dictionary<string, AudioClip> SLoadedAudios = new Dictionary<string, AudioClip>();
        public static Dictionary<string, GameObject> SLoadedMaps = new Dictionary<string, GameObject>();
        public static Dictionary<string, GameObject> SLoadedEffects = new Dictionary<string, GameObject>();
        public static Dictionary<string, SkeletonDataAsset> SLoadedSkeletonDataAsset = new Dictionary<string, SkeletonDataAsset>();
        public static Dictionary<string, Material> SLoadedMaterial = new Dictionary<string, Material>();

        public static Material Pet_Copy_Mat = null;

        static Dictionary<string, List<GameObject>> skeletonGraphicMap = new Dictionary<string, List<GameObject>>();

        static Dictionary<string, CacheObject> prefabRefMap = new Dictionary<string, CacheObject>();
        static Dictionary<string, CacheObject> mapRefMap = new Dictionary<string, CacheObject>();
        static Dictionary<string, CacheObject> effectRefMap = new Dictionary<string, CacheObject>();
        static Dictionary<string, CacheObject> spriteRefMap = new Dictionary<string, CacheObject>();

        GameObject videoObj = null;

        static int prefabRefIndex = 0;
        static int mapRefIndex = 0;
        static int effectRefIndex = 0;

        public static ResourceManager Instance;

        public static ResourceManager GetResourceManager()
        {
            return Instance;
        }

        private void Awake()
        {
            Instance = this;
        }

        private readonly List<string> _isDownLoadingAbName = new List<string>();

        private class LoadAssetRequest
        {
            public Type AssetType;
            public string[] AssetNames;
            public LuaFunction LuaFunc;
            public Action<UObject[]> SharpFunc;
            public Action<AssetBundle> BundleFunc;
        }

        // Load AssetBundleManifest.
        public void Initialize(string manifestName, Action initOk)
        {
            //m_BaseDownloadingURL = Util.GetRelativePath();
            //Util.Log(m_BaseDownloadingURL);

            if (AppConst.BundleMode)
                SpriteAtlasManager.atlasRequested += OnAtlasRequest;


#if !UNITY_EDITOR || CLIENT_BUNDLE
            var dataPath = Util.GetDataPath();
            var resPath = Util.AppContentPath(); //游戏包资源目录

            //资源清单 如果游戏资源目录存在，就用新的，否则用旧的
            string manifestFilePath;
            if (File.Exists(dataPath + manifestName))
            {
                manifestFilePath = dataPath + manifestName;
            }
            else
            {
                manifestFilePath = resPath + manifestName;
            }
            Util.Log("manifestFilePath:" + manifestFilePath);
            AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
            mAssetBundleManifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            _mAllManifest = mAssetBundleManifest.GetAllAssetBundles();
            string[] dependencies = mAssetBundleManifest.GetAllDependencies("assetBundle"); //Pass the name of the bundle you want the dependencies for.

            foreach (string dependency in dependencies)
            {
                Util.Log("dataPath:" + dataPath);
                AssetBundle.LoadFromFile(Path.Combine(dataPath, dependency));
            }
#endif
            initOk?.Invoke();
        }

        private void Update()
        {
            UIPackageResManager.Instance.Update();
        }

        private static string GetPureName(string assetName)
        {
            if (assetName.StartsWith("model/drawing") || assetName.StartsWith("model/role") || assetName.StartsWith("prefabs/skill"))
            {
                return assetName;
            }
            var names = assetName.Split('/');
            var abName = names[names.Length - 1];
            abName = abName.ToLower();

            return abName;
        }

        public void DestoryPartices(GameObject particle)
        {
            if (particle)
            {
                UISpineDestroyer destroyer = particle.GetComponent<UISpineDestroyer>();

                if (destroyer)
                {
                    if (skeletonGraphicMap.ContainsKey(destroyer._url))
                    {
                        List<GameObject> graphics = skeletonGraphicMap[destroyer._url];
                        graphics.Remove(particle);
                    }
                }

                particle.SetActive(false);
                particle.transform.SetParent(null, false);
                GameObject.Destroy(particle);
            }
        }

        public void DestroyUISpine(GameObject ui)
        {
            UISpineDestroyer destroyer = ui.GetComponent<UISpineDestroyer>();
            if (destroyer != null)
            {
                destroyer.isUse = false;
                ui.SetActive(false);
                ui.transform.SetParent(null, false);
            }
            else
            {
                ui.SetActive(false);
                ui.transform.SetParent(null, false);
                GameObject.Destroy(ui);
            }
        }

        public GameObject GetUISpine(string name, GameObject prefab)
        {
            SkeletonGraphic graphic = prefab.GetComponent<SkeletonGraphic>();
            if (graphic == null)
            {
                return prefab;
            }
            if (graphic.allowMultipleCanvasRenderers == false)
            {
                return prefab;
            }
            if (skeletonGraphicMap.ContainsKey(name))
            {
                for (int i = 0; i < skeletonGraphicMap[name].Count; i++)
                {
                    GameObject obj = skeletonGraphicMap[name][i];
                    UISpineDestroyer destroyer = obj.GetComponent<UISpineDestroyer>();
                    if (destroyer != null && destroyer.isUse == false)
                    {
                        destroyer.isUse = true;
                        obj.SetActive(true);
                        return obj;
                    }
                }
                {
                    GameObject obj = GameObject.Instantiate(prefab);
                    UISpineDestroyer destroyer = obj.AddComponent<UISpineDestroyer>();
                    destroyer._url = name;
                    destroyer.isUse = true;
                    skeletonGraphicMap[name].Add(obj);
                    obj.SetActive(true);
                    return obj;
                }
            }
            else
            {
                skeletonGraphicMap.Add(name, new List<GameObject>());
                GameObject obj = GameObject.Instantiate(prefab);
                UISpineDestroyer destroyer = obj.AddComponent<UISpineDestroyer>();
                destroyer._url = name;
                destroyer.isUse = true;
                skeletonGraphicMap[name].Add(obj);
                obj.SetActive(true);
                return obj;
            }
        }

        //加载声音 for c#
        public void LoadAudioPrefab(string assetName, Action<AudioClip> action)
        {
            assetName = assetName.ToLower();
            if (SLoadedAudios.ContainsKey(assetName))
            {
                // ReSharper disable once SuggestVarOrType_SimpleTypes
                AudioClip prefab = SLoadedAudios[assetName];
                if (prefab != null)
                {
                    action?.Invoke(prefab);
                }
                return;
            }
            LoadAudioPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length > 0 && objs[0] != null)
                {
                    var prefab = objs[0] as AudioClip;
                    if (prefab == null) return;
                    if (!SLoadedAudios.ContainsKey(assetName))
                    {
                        SLoadedAudios.Add(assetName, prefab);
                    }

                    action?.Invoke(prefab);
                }
            });
        }

        public void ClearBattleResRef()
        {
            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && (prefab.Key.StartsWith("model/drawing") || prefab.Key.StartsWith("prefabs/skill") || prefab.Key.StartsWith("model/role")))
                {
                    prefabRef.refCount = 0;
                }
            }

            foreach (var map in SLoadedMaps)
            {
                var mapRef = mapRefMap[map.Key];
                if( mapRef != null )
                {
                    mapRef.refCount = 0;
                }
            }
        }

        public void UpdateResTime(string assetName, string type)
        {
            if ("Model" == type || "Effect" == type)
            {
                if (prefabRefMap.ContainsKey(assetName.ToLower()))
                {
                    prefabRefMap[assetName.ToLower()].lastRefTime = Time.realtimeSinceStartup;
                    prefabRefMap[assetName.ToLower()].refCount = 1;
                }
            }
            /*
            else if ("Effect" == type)
            {
                if (effectRefMap.ContainsKey(assetName.ToLower()))
                {
                    effectRefMap[assetName.ToLower()].lastRefTime = Time.realtimeSinceStartup;
                }
            }
            */
            else if ("Map" == type)
            {
                if (mapRefMap.ContainsKey(assetName.ToLower()))
                {
                    mapRefMap[assetName.ToLower()].lastRefTime = Time.realtimeSinceStartup;
                    mapRefMap[assetName.ToLower()].refCount = 1;
                }
            }
        }

        //加载声音 for lua
        public void LoadAudioPrefab(string assetName, LuaFunction func)
        {
            //Util.LogError("LoadAudioPrefab:" + assetName);
            assetName = assetName.ToLower();
            if (SLoadedAudios.ContainsKey(assetName))
            {
                var prefab = SLoadedAudios[assetName];
                if (prefab != null && func != null)
                {
                    func.Call(prefab);
                }
                return;
            }
            LoadAudioPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as AudioClip;
                if (prefab == null) return;
                if (!SLoadedAudios.ContainsKey(assetName))
                {
                    SLoadedAudios.Add(assetName, prefab);
                }
                if (func != null)
                    func.Call(prefab);
            });
        }

        //加载视频 for lua
        public void UnloadVideo(GameObject assert)
        {
            if (videoObj != null)
                Resources.UnloadAsset(videoObj); 
        }
        public void LoadVideoPrefab(string assetName, LuaFunction func)
        {
            string resPath = assetName;
            GameObject prefab = Resources.Load<GameObject>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找资源:" + assetName);
                return;
            }
            videoObj = prefab;
            if (func != null)
            {
                func.Call(prefab);
            }

            // assetName = assetName.ToLower();
            // if (ResourceManager.SLoadedAudios.ContainsKey(assetName))
            // {
            //     //UnityEngine.Video.VideoClip prefab = ResourceManager.s_LoadedAudios[assetName];
            //     //if (prefab != null && func != null)
            //     //{
            //     //func.Call(prefab);
            //     //}
            //     return;
            // }
            // LoadVideoPrefab(assetName, delegate (UObject[] objs)
            // {
            //     if (objs.Length <= 0 || objs[0] == null) return;
            //     var prefab = objs[0] as UnityEngine.Video.VideoClip;
            //     if (prefab == null) return;
            //     //if (!ResourceManager.s_LoadedAudios.ContainsKey(assetName))
            //     // {
            //     // ResourceManager.s_LoadedAudios.Add(assetName, prefab);
            //     //}
            //     if (func != null)
            //         func.Call(prefab);
            // });
        }

        //加载字体 for lua
        public void LoadFontPrefab(string assetName, LuaFunction func)
        {
            assetName = assetName.ToLower();
            LoadFontPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as TMPro.TMP_FontAsset;
                if (prefab != null && func != null)
                {
                    func.Call(prefab);
                }
            });
        }

        public void UnloadSpitePrefab(string assetName)
        {
            assetName = assetName.ToLower();
            if (!AppConst.BundleMode)
            {

            }
            else
            {
                var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);

                if (spriteRefMap.ContainsKey(assetName) && SLoadedSprites.ContainsKey(assetName))
                {
                    spriteRefMap[assetName].refCount--;

                    if (spriteRefMap[assetName].refCount <= 0 )// && assetName.IndexOf("00_common_frame_tc_") == -1)
                    {
                        GameObject.DestroyImmediate(SLoadedSprites[assetName], true);
                        SLoadedSprites.Remove(assetName);
                        spriteRefMap.Remove(assetName);

                        var names = assetName.Split('/');
                        var abName = names[names.Length - 1];
                        abName = abName.ToLower();

                        var abName2 = resManager.GetRealAssetPath(abName);

                        if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                        {
                            var asset = resManager._mLoadedAssetBundles[abName2];
                            if (asset != null)
                            {
                                if (asset.MAssetBundle != null)
                                    asset.MAssetBundle.Unload(true);
                                asset = null;
                                resManager._mLoadedAssetBundles.Remove(abName2);
                            }
                        }
                    }
                }
            }
            return;
        }

        //加载sprite for c#
        public void LoadSpritePrefab(string assetName, Action<Sprite> action)
        {
            assetName = assetName.ToLower();
            if (ResourceManager.SLoadedSprites.ContainsKey(assetName))
            {
                var prefab = ResourceManager.SLoadedSprites[assetName];
                if (prefab != null && action != null)
                {
                    if (spriteRefMap.ContainsKey(assetName))
                    {
                        spriteRefMap[assetName].lastRefTime = Time.realtimeSinceStartup;
                        spriteRefMap[assetName].refCount++;
                    }
                    action(prefab);
                }
                return;
            }
            LoadSpritePrefab(assetName, delegate (UObject[] objs)
            {
                if (objs == null)
                {
                    return;
                }
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as Sprite;
                if (prefab == null) return;

                if (!ResourceManager.SLoadedSprites.ContainsKey(assetName))
                {
                    ResourceManager.SLoadedSprites.Add(assetName, prefab);
                    if (!spriteRefMap.ContainsKey(assetName))
                    {
                        CacheObject spriteRef = new CacheObject();
                        spriteRef.refCount++;
                        spriteRefMap.Add(assetName, spriteRef);
                    }
                }
                else
                {
                    if (spriteRefMap.ContainsKey(assetName))
                    {
                        spriteRefMap[assetName].lastRefTime = Time.realtimeSinceStartup;
                        spriteRefMap[assetName].refCount++;
                    }
                }

                action?.Invoke(prefab);
            });
        }

        //加载sprite for lua
        public void LoadSpritePrefab(string assetName, LuaFunction func)
        {
            //Util.LogError("LoadSpritePrefab:" + assetName);
            assetName = assetName.ToLower();
            if (ResourceManager.SLoadedSprites.ContainsKey(assetName))
            {
                var prefab = ResourceManager.SLoadedSprites[assetName];
                if (prefab != null && func != null)
                {
                    func.Call(prefab);
                }
                return;
            }
            LoadSpritePrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as Sprite;
                if (prefab == null) return;
                if (!SLoadedSprites.ContainsKey(assetName))
                {
                    SLoadedSprites.Add(assetName, prefab);
                }
                if (func != null)
                    func.Call(prefab);
            });
        }
        public void DestroySprite(string assetName)
        {
            if (SLoadedSprites.ContainsKey(assetName))
            {
                var sp = SLoadedSprites[assetName];
                if (sp != null)
                    DestroyImmediate(sp, true);
                SLoadedSprites.Remove(assetName);

                if (AppConst.BundleMode)
                {
                    var names = assetName.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = GetRealAssetPath(abName);

                    if (_mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = _mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            _mLoadedAssetBundles.Remove(abName2);
                        }
                    }
                }
            }
        }
        //加载Icon for lua
        public void LoadIconFromPrefab(string assetName, string iconName, LuaFunction func)
        {
            assetName = assetName.ToLower();
            //iconName = iconName.ToLower();
            if (SLoadedSprites.ContainsKey(iconName))
            {
                Sprite prefab = SLoadedSprites[iconName];
                if (prefab != null && func != null)
                {
                    func.Call(prefab);
                }
                return;
            }

            //Util.Log("LoadIconFromPrefab for lua:" + assetName + iconName);
            if (SLoadedSpriteAtlas.ContainsKey(assetName))
            {
                var spriteAtlas = SLoadedSpriteAtlas[assetName];
                if (spriteAtlas == null) return;
                var sp = spriteAtlas.GetSprite(iconName);
                if (sp == null) return;
                if (!SLoadedSprites.ContainsKey(iconName))
                {
                    SLoadedSprites.Add(iconName, sp);
                }
                if (func != null)
                    func.Call(sp);
                return;
            }
            LoadIconFromPrefab(assetName, iconName, delegate (UObject[] objs)
            {
                //Util.Log("assetName1:" + assetName + objs.Length);
                if (objs.Length <= 0 || objs[0] == null) return;
                var spriteAtlas = objs[0] as SpriteAtlas;
                if (spriteAtlas == null) return;
                if (!SLoadedSpriteAtlas.ContainsKey(assetName))
                {
                    SLoadedSpriteAtlas.Add(assetName, spriteAtlas);
                }
                var sp = spriteAtlas.GetSprite(iconName);
                if (sp == null) return;
                if (!SLoadedSprites.ContainsKey(iconName))
                {
                    SLoadedSprites.Add(iconName, sp);
                }
                if (func != null)
                    func.Call(sp);
            });
        }

        //加载Icon for c#
        public void LoadIconFromPrefab(string assetName, string iconName, Action<Sprite> action)
        {
            assetName = assetName.ToLower();
            //iconName = iconName.ToLower();
            if (SLoadedSprites.ContainsKey(iconName))
            {
                var prefab = SLoadedSprites[iconName];
                if (prefab != null && action != null)
                {
                    action(prefab);
                }
                return;
            }

            //Util.Log("LoadIconFromPrefab for c#:" + assetName + iconName);
            if (SLoadedSpriteAtlas.ContainsKey(assetName))
            {
                var spriteAtlas = SLoadedSpriteAtlas[assetName];
                if (spriteAtlas == null) return;
                var sp = spriteAtlas.GetSprite(iconName);
                if (sp == null) return;
                if (!SLoadedSprites.ContainsKey(iconName))
                {
                    SLoadedSprites.Add(iconName, sp);
                }

                action?.Invoke(sp);
                return;
            }

            LoadIconFromPrefab(assetName, iconName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var spriteAtlas = objs[0] as SpriteAtlas;
                if (spriteAtlas == null) return;
                if (!SLoadedSpriteAtlas.ContainsKey(assetName))
                {
                    SLoadedSpriteAtlas.Add(assetName, spriteAtlas);
                }
                var sp = spriteAtlas.GetSprite(iconName);
                if (sp == null) return;
                if (!SLoadedSprites.ContainsKey(iconName))
                {
                    SLoadedSprites.Add(iconName, sp);
                }

                action?.Invoke(sp);
            });
        }

        //加载UI for c#
        public void LoadUIPrefab(string assetName, Action<GameObject> action)
        {
            assetName = assetName.ToLower();
            //Util.Log("LoadUIPrefab for c#:" + assetName);
            LoadUIPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab != null)
                {
                    action?.Invoke(prefab);
                }
            });
        }


        //加载fgUI for c#
        public void LoadFUIPrefab(string assetName, Action action = null)
        {
            assetName = assetName.ToLower();
            //Util.Log("LoadFUIPrefab for c#:" + assetName);
            LoadFUIPrefab(assetName, delegate (AssetBundle objs)
            {
                if (objs != null)
                {
                    FairyGUI.UIPackage.AddFuiBundle(assetName, objs);
                }
                else
                {
                    //Util.Log("ERRRRRRRRRRRRRRRRRRLoadUIPrefab for c#AssetBundle:"+assetName);
                }
                if (action != null && objs != null)
                {
                    action();
                }
            });
        }

        //加载UI for lua
        public void LoadUIPrefab(string assetName, LuaFunction func)
        {
            assetName = assetName.ToLower();
            Util.Log("LoadUIPrefab for lua:" + assetName);
            LoadUIPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab != null && func != null)
                {
                    func.Call(prefab);
                }
            });
        }

        //加载gameobject for c#
        public void LoadPrefab(string assetName, Action<GameObject> action)
        {
            //Util.LogError("LoadPrefab:" + assetName);
            assetName = assetName.ToLower();
            var pureName = GetPureName(assetName);
            if (SLoadedPrefabs.ContainsKey(pureName))
            {
                var prefab = SLoadedPrefabs[pureName];
                var prefabRef = prefabRefMap[pureName];
                if (prefab != null && action != null)
                {
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                    action(prefab);
                }
                return;
            }
            //Util.Log("LoadPrefab for c#:" + assetName);
            LoadPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;
                if (!SLoadedPrefabs.ContainsKey(pureName))
                {
                    SLoadedPrefabs.Add(pureName, prefab);

                    CacheObject prefabRef = new CacheObject();
                    prefabRef.refCount++;
                    prefabRefMap.Add(pureName, prefabRef);
                }
                else
                {
                    var prefabRef = prefabRefMap[pureName];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                }

                action?.Invoke(prefab);
            });
        }

        //加载gameobject for lua
        public void LoadPrefab(string assetName, LuaFunction func, object parm = null)
        {
            //Util.LogError("LoadPrefab:" + assetName);
            assetName = assetName.ToLower();
            var pureName = GetPureName(assetName);
            if (SLoadedPrefabs.ContainsKey(pureName))
            {
                var prefab = SLoadedPrefabs[pureName];
                var prefabRef = prefabRefMap[pureName];
                if (prefab == null || func == null) return;

                if (prefabRef != null)
                {
                    prefabRef.lastRefTime = Time.realtimeSinceStartup;
                    prefabRef.refCount++;
                }

                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
                return;
            }
            //Util.Log("LoadPrefab for lua:" + assetName);
            LoadPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;
                if (!SLoadedPrefabs.ContainsKey(pureName))
                {
                    SLoadedPrefabs.Add(pureName, prefab);

                    CacheObject prefabRef = new CacheObject();
                    prefabRef.refCount++;
                    prefabRefMap.Add(pureName, prefabRef);
                }
                else
                {
                    var prefabRef = prefabRefMap[pureName];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                }

                if (func == null) return;

                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
            });
        }

        //加载Model for c#
        public void LoadModelPrefab(string assetName, Action<GameObject> action)
        {
            //Util.LogError("LoadModelPrefab:" + assetName);
            assetName = assetName.ToLower();
            var pureName = GetPureName(assetName);

            if (SLoadedPrefabs.ContainsKey(pureName))
            {
                var prefab = ResourceManager.SLoadedPrefabs[pureName];
                var prefabRef = prefabRefMap[pureName];
                if (prefab != null)
                {
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                    action?.Invoke(prefab);
                }
                return;
            }
            //Util.Log("LoadModelPrefab for c#:" + assetName);
            LoadModelPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;

                if (!SLoadedPrefabs.ContainsKey(pureName))
                {
                    SLoadedPrefabs.Add(pureName, prefab);

                    CacheObject prefabRef = new CacheObject();
                    prefabRef.refCount++;
                    prefabRefMap.Add(pureName, prefabRef);
                }
                else
                {
                    var prefabRef = prefabRefMap[pureName];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                }

                action?.Invoke(prefab);
            });
        }

        //加载LoadModelPrefab for lua

        public void LoadModelPrefab(string assetName, LuaFunction func, object parm = null)
        {
            //Util.LogError("LoadModelPrefab:" + assetName);

            assetName = assetName.ToLower();
            var pureName = GetPureName(assetName);

            if (SLoadedPrefabs.ContainsKey(pureName))
            {
                var prefab = SLoadedPrefabs[pureName];
                var prefabRef = prefabRefMap[pureName];
                if (prefab == null || func == null) return;

                if (prefabRef != null)
                {
                    prefabRef.lastRefTime = Time.realtimeSinceStartup;
                    prefabRef.refCount++;
                }

                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
                return;
            }
            bool needCache = true;
            if (parm != null)
            {
                if (parm is bool)
                {
                    needCache = (bool)parm;
                }
            }
            //Util.Log("LoadModelPrefab for lua:" + assetName);
            LoadModelPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;

                if (pureName.IndexOf("pet_100001") != -1)
                {
                    SkeletonGraphic graphic = prefab.GetComponent<SkeletonGraphic>();
                    Pet_Copy_Mat = new Material(graphic.material);
                    Pet_Copy_Mat.name = "AlwaysShader";
                }
                if (needCache && !SLoadedPrefabs.ContainsKey(pureName))
                {
                    SLoadedPrefabs.Add(pureName, prefab);

                    CacheObject prefabRef = new CacheObject();
                    prefabRef.refCount++;
                    prefabRefMap.Add(pureName, prefabRef);
                }
                else if (needCache)
                {
                    var prefabRef = prefabRefMap[pureName];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                        prefabRef.refCount++;
                    }
                }

                if (func == null) return;

                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
            });
        }
        //加载特效
        private void LoadMaterial(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                var resPath = assetName;
                Material prefab = null;//Resources.Load<Material>(resPath);
#if UNITY_EDITOR && !CLIENT_BUNDLE
                prefab = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Project/" + assetName + ".mat", typeof(Material)) as Material;
#endif

                if (prefab == null)
                {
                    Util.LogError("未找资源:" + assetName);
                    return;
                }
                if (action != null)
                {
                    action(new UObject[] { prefab });
                }
                if (func != null)
                {
                    func.Call(prefab);
                }
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundleAsync<Material>(abName, action, func);
            }
        }
        public void LoadMaterial(string assetName, LuaFunction func, object parm = null)
        {
            assetName = assetName.ToLower();
            if (SLoadedMaterial.ContainsKey(assetName))
            {
                var prefab = SLoadedMaterial[assetName];
                if (prefab == null || func == null) return;
                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
                return;
            }
            //Util.Log("LoadEffectPrefab for lua:" + assetName);
            LoadMaterial(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as Material;
                if (prefab == null) return;
                if (!SLoadedMaterial.ContainsKey(assetName))
                {
                    SLoadedMaterial.Add(assetName, prefab);
                }

                if (func == null) return;
                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
            });
        }

        //加载特效
        private void LoadSpineAsset(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                var resPath = assetName;
                var prefab = Resources.Load<SkeletonDataAsset>(resPath);
                if (prefab == null)
                {
                    Util.LogError("未找资源:" + assetName);
                    return;
                }

                action?.Invoke(new UObject[] { prefab });
                if (func != null)
                {
                    func.Call(prefab);
                }
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundleAsync<SkeletonDataAsset>(abName, action, func);
            }
        }
        public void LoadSpineAsset(string assetName, LuaFunction func, object parm = null)
        {
            assetName = assetName.ToLower();
            if (SLoadedSkeletonDataAsset.ContainsKey(assetName))
            {
                SkeletonDataAsset prefab = SLoadedSkeletonDataAsset[assetName];
                if (prefab != null && func != null)
                {
                    if (parm != null)
                        func.Call(prefab, parm);
                    else
                        func.Call(prefab);
                }
                return;
            }
            //Util.Log("LoadEffectPrefab for lua:" + assetName);
            LoadSpineAsset(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as SkeletonDataAsset;
                if (prefab == null) return;
                if (!SLoadedSkeletonDataAsset.ContainsKey(assetName))
                {
                    SLoadedSkeletonDataAsset.Add(assetName, prefab);
                }

                if (func == null) return;
                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
            });
        }

        //       // 

        //加载LoadEffectPrefab for lua
        public void LoadEffectPrefab(string assetName, LuaFunction func, object parm = null)
        {
            //Util.LogError("LoadEffectPrefab:" + assetName);
            assetName = assetName.ToLower();
            if (SLoadedEffects.ContainsKey(assetName))
            {
                var prefab = SLoadedEffects[assetName];
                var prefabRef = effectRefMap[assetName];
                if (prefab == null || func == null) return;
                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
                if (prefabRef != null)
                {
                    prefabRef.lastRefTime = Time.realtimeSinceStartup;
                }
                return;
            }
            //Util.Log("LoadEffectPrefab for lua:" + assetName);
            LoadEffectPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;
                if (!SLoadedEffects.ContainsKey(assetName))
                {
                    SLoadedEffects.Add(assetName, prefab);

                    CacheObject effectRef = new CacheObject();
                    effectRefMap.Add(assetName, effectRef);
                }

                if (func == null) return;
                if (parm != null)
                    func.Call(prefab, parm);
                else
                    func.Call(prefab);
            });
        }


        //加载Map for lua
        public void LoadMapPrefab(string assetName, LuaFunction func)
        {
            //Util.LogError("LoadMapPrefab:" + assetName);
            assetName = assetName.ToLower();
            if (SLoadedMaps.ContainsKey(assetName))
            {
                var prefab = SLoadedMaps[assetName];
                var prefabRef = mapRefMap[assetName];
                if (prefab == null || func == null) return;
                func.Call(prefab);
                if (prefabRef != null)
                {
                    prefabRef.lastRefTime = Time.realtimeSinceStartup;
                }
                return;
            }
            //Util.Log("LoadMapPrefab for lua:" + assetName);
            LoadMapPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;

                if (!SLoadedMaps.ContainsKey(assetName))
                {
                    SLoadedMaps.Add(assetName, prefab);

                    CacheObject mapRef = new CacheObject();
                    mapRefMap.Add(assetName, mapRef);
                }
                if (func != null)
                    func.Call(prefab);
            });
        }

        //加载Map for lc#
        public void LoadMapPrefab(string assetName, [CanBeNull] Action<GameObject> action)
        {
            //Util.LogError("LoadMapPrefab:" + assetName);
            assetName = assetName.ToLower();
            if (SLoadedMaps.ContainsKey(assetName))
            {
                var prefab = SLoadedMaps[assetName];
                var prefabRef = mapRefMap[assetName];
                if (prefab != null)
                {
                    action?.Invoke(prefab);

                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                    }
                }
                return;
            }
            //Util.Log("LoadMapPrefab for che#:" + assetName);
            LoadMapPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as GameObject;
                if (prefab == null) return;
                if (!SLoadedMaps.ContainsKey(assetName))
                {
                    SLoadedMaps.Add(assetName, prefab);

                    CacheObject mapRef = new CacheObject();
                    mapRefMap.Add(assetName, mapRef);
                }

                action?.Invoke(prefab);
            });
        }

        //加载SpriteAtlas for lua
        public void LoadSpriteAtlasPrefab(string assetName, LuaFunction func)
        {
            //Util.LogError("LoadSpriteAtlasPrefab:" + assetName);
            assetName = assetName.ToLower();
            //Util.Log("LoadSpriteAtlasPrefab for lua:" + assetName);
            if (SLoadedSpriteAtlas.ContainsKey(assetName))
            {
                func.Call(SLoadedSpriteAtlas[assetName]);
                return;
            }

            LoadSpriteAtlasPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as SpriteAtlas;
                if (prefab == null) return;
                if (SLoadedSpriteAtlas.ContainsKey(assetName))
                {
                    if (func != null)
                        func.Call(SLoadedSpriteAtlas[assetName]);
                    return;
                }
                SLoadedSpriteAtlas.Add(assetName, prefab);
                if (func != null)
                    func.Call(prefab);
            });
        }

        //加载SpriteAtlas for lc#
        public void LoadSpriteAtlasPrefab(string assetName, Action<SpriteAtlas> action)
        {
            //Util.LogError("LoadSpriteAtlasPrefab:" + assetName);
            assetName = assetName.ToLower();
            //Util.Log("LoadSpriteAtlasPrefab for c#:" + assetName);
            if (SLoadedSpriteAtlas.ContainsKey(assetName))
            {
                action?.Invoke(SLoadedSpriteAtlas[assetName]);
                return;
            }

            LoadSpriteAtlasPrefab(assetName, delegate (UObject[] objs)
            {
                if (objs.Length <= 0 || objs[0] == null) return;
                var prefab = objs[0] as SpriteAtlas;
                if (prefab == null) return;
                if (SLoadedSpriteAtlas.ContainsKey(assetName))
                {
                    action?.Invoke(SLoadedSpriteAtlas[assetName]);
                    return;
                }
                SLoadedSpriteAtlas.Add(assetName, prefab);
                action?.Invoke(prefab);
            });
        }

        //加载gameobject
        private void LoadPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            //Util.LogError("LoadPrefab:" + assetName);
            if (!AppConst.BundleMode)
            {
                LoadGameObject(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<GameObject>(abName, action, func);
            }
        }

        //加载Model
        public void LoadModelPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadGameObject(assetName, action, func);
            }
            else
            {
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundleAsync<GameObject>(abName, action, func);
            }
        }


        //加载特效
        public void LoadEffectPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadGameObject(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundleAsync<GameObject>(abName, action, func);
            }
        }


        //加载Map
        public void LoadMapPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadGameObject(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                //LoadAssetBundle<GameObject>(ABName, action, func);
                LoadAssetBundleAsync<GameObject>(abName, action, func);
            }
        }

        //加载声音
        public void LoadAudioPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadAudio(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<AudioClip>(abName, action, func);
            }
        }

        //加载声音
        protected void LoadVideoPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadVideo(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<UnityEngine.Video.VideoClip>(abName, action, func);
            }
        }
        //加载字体        

        protected void LoadFontPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadFont(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<TMPro.TMP_FontAsset>(abName, action, func);
                LoadAssetBundle<Material>(abName, action, func);
            }
        }

        //加载sprite
        protected void LoadSpritePrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadSprite(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<Sprite>(abName, action, func);
            }
        }

        //加载Icon
        protected void LoadIconFromPrefab(string assetName, string iconName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadIcon(assetName, action, func);
            }
            else
            {
                //蛋疼，两边路径不一样，先临时处理一下
                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();
                LoadAssetBundle<SpriteAtlas>(abName, action, func);
            }
        }

        //加载图片
        protected void LoadTexturePrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            if (!AppConst.BundleMode)
            {
                LoadTexture(assetName, action, func);
            }
            else
            {
                LoadAssetBundle<Texture2D>(assetName, action, func);
            }
        }

        //加载UI
        protected void LoadUIPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            //Util.LogError("LoadUIPrefab:" + assetName);
            if (!AppConst.BundleMode)
            {
                LoadUI(assetName, action, func);
            }
            else
            {
                LoadAssetBundle<GameObject>(assetName, action, func);
            }
        }

        //加载UI
        public void LoadFUIPrefab(string assetName, Action<AssetBundle> action, LuaFunction func = null)
        {
            //Util.LogError("LoadFUIPrefab:" + assetName);
            LoadAssetBundlefui(assetName, action, func);
        }

        protected void LoadSpriteAtlasPrefab(string assetName, Action<UObject[]> action, LuaFunction func = null)
        {
            //Util.LogError("LoadSpriteAtlasPrefab:" + assetName);
            if (!AppConst.BundleMode)
            {
                LoadSpriteAtlas(assetName, action, func);
            }
            else
            {
                LoadAssetBundle<SpriteAtlas>(assetName, action, func);
            }
        }

        protected void LoadAudio(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            //Util.LogError("LoadAudio:" + assetName);
            AudioClip prefab = null;
#if UNITY_EDITOR && !CLIENT_BUNDLE
            prefab =UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Project/"+assetName+".ogg", typeof(AudioClip)) as AudioClip;
#endif
            //AudioClip prefab = Resources.Load<AudioClip>(assetName);
            if (prefab == null)
            {
                Util.LogError("未找到声音资源:" + assetName);
                return;
            }

            action?.Invoke(new UObject[] { prefab });
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadVideo(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            UnityEngine.Video.VideoClip prefab;
#if UNITY_EDITOR && !CLIENT_BUNDLE
            prefab =UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Project/"+assetName+".mp4", typeof(UnityEngine.Video.VideoClip)) as UnityEngine.Video.VideoClip;
#else
            prefab = null;
#endif
            if (prefab == null)
            {
                Util.LogError("未找到视频资源:" + assetName);
                return;
            }

            action?.Invoke(new UObject[] { prefab });
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadFont(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            //Util.LogError("LoadFont:" + assetName);
            var resPath = "Atlas/" + assetName;
            var prefab = Resources.Load<GameObject>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找到字体资源:" + assetName);
                return;
            }

            action?.Invoke(new UObject[] { prefab });
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadSprite(string assetName, Action<UObject[]> action = null, [CanBeNull] LuaFunction func = null)
        {
            // string resourPath = "Textures/BGPic/" + assetName ;
            // string resourPath2 = "Textures/Lihui/" + assetName ;
            // string resourPath3 = "Textures/spskill/" + assetName;
            // string resourPath4 = "Textures/story/" + assetName;
            // Sprite prefab = Resources.Load<Sprite>(resourPath);
            // if (prefab == null)
            // {
            //     prefab = Resources.Load<Sprite>(resourPath2);
            // }
            // if (prefab == null)
            // {
            //     prefab = Resources.Load<Sprite>(resourPath3);
            // }
            // if (prefab == null)
            // {
            //     prefab = Resources.Load<Sprite>(resourPath4);
            // }
            Sprite prefab = null;
            {
                var resPath = Application.dataPath + "/Project/Textures/BGPic/" + assetName + ".png";
                var resPath2 = Application.dataPath + "/Project/Textures/Lihui/" + assetName + ".png";
                var resPath3 = Application.dataPath + "/Project/Textures/spskill/" + assetName + ".png";
                var resPath4 = Application.dataPath + "/Project/Textures/story/" + assetName + ".png";
                string endstr = MulLanguageUtil.GetBranchEndString(LanguageManager.Instance.language);

                if (File.Exists(resPath))
                {
                    string branchpath = Application.dataPath + "/Project/Textures/BGPic_" + endstr + "/" + assetName + ".png";

                    FileStream fs;
                    if(AppConst.LanguageMode && File.Exists(branchpath))
                    {
                        fs = new FileStream(branchpath, FileMode.Open, FileAccess.Read);
                    }
                    else
                    {
                        fs = new FileStream(resPath, FileMode.Open, FileAccess.Read);
                    }

                    fs.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[fs.Length];

                    fs.Read(bytes, 0, (int)fs.Length);
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                    //创建Texture
                    var texture2D = new Texture2D(1, 1);
                    texture2D.LoadImage(bytes);
                    prefab = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
                }
                if (File.Exists(resPath2))
                {
                    var fs = new FileStream(resPath2, FileMode.Open, FileAccess.Read);
                    fs.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[fs.Length];

                    fs.Read(bytes, 0, (int)fs.Length);
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                    //创建Texture
                    var texture2D = new Texture2D(1, 1);
                    texture2D.LoadImage(bytes);
                    prefab = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
                }
                if (File.Exists(resPath3))
                {
                    var fs = new FileStream(resPath3, FileMode.Open, FileAccess.Read);
                    fs.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[fs.Length];

                    fs.Read(bytes, 0, (int)fs.Length);
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                    //创建Texture
                    var texture2D = new Texture2D(1, 1);
                    texture2D.LoadImage(bytes);
                    prefab = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
                }
                if (File.Exists(resPath4))
                {
                    var fs = new FileStream(resPath4, FileMode.Open, FileAccess.Read);
                    fs.Seek(0, SeekOrigin.Begin);
                    var bytes = new byte[fs.Length];

                    fs.Read(bytes, 0, (int)fs.Length);
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                    //创建Texture
                    var texture2D = new Texture2D(1, 1);
                    texture2D.LoadImage(bytes);
                    prefab = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
                }
            }
            if (prefab == null)
            {
                Util.LogError("未找到贴图资源:" + assetName);
                return;
            }
            if (action != null)
            {
                action(new UObject[] { prefab });
            }
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadSpriteAtlas(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            Util.LogError("LoadSpriteAtlas:" + assetName);
            var resPath = "Atlas/" + assetName;
            var prefab = Resources.Load<SpriteAtlas>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找图集资源:" + assetName);
                return;
            }

            action?.Invoke(new UObject[] { prefab });
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadTexture(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            Util.LogError("LoadTexture:" + assetName);
            var prefab = Resources.Load<Texture2D>(assetName);
            if (prefab == null)
            {
                Util.LogError("未找图片资源:" + assetName);
                return;
            }

            action?.Invoke(new UObject[] { prefab });
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadUI(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            string resPath = "UI/" + assetName;
            GameObject prefab = Resources.Load<GameObject>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找UI资源:" + assetName);
                return;
            }
            if (action != null)
            {
                action(new UObject[] { prefab });
            }
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadGameObject(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            string resPath = assetName;
            GameObject prefab = null;
#if UNITY_EDITOR && !CLIENT_BUNDLE
            prefab =UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Project/"+assetName+".prefab", typeof(GameObject)) as GameObject;
#endif
            //GameObject prefab = Resources.Load<GameObject>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找资源:" + assetName);
                return;
            }
            if (action != null)
            {
                action(new UObject[] { prefab });
            }
            if (func != null)
            {
                func.Call(prefab);
            }
        }

        protected void LoadIcon(string assetName, Action<UObject[]> action = null, LuaFunction func = null)
        {
            var resPath = "atlas/" + assetName;
            var prefab = Resources.Load<SpriteAtlas>(resPath);
            if (prefab == null)
            {
                Util.LogError("未找Icon资源:" + resPath);
                return;
            }
            if (action != null)
            {
                action(new UObject[] { prefab });
            }
            if (func != null)
            {
                func.Call(prefab);
            }

        }

        void LoadAssetBundle<T>(string abName, Action<UObject[]> action = null, LuaFunction func = null) where T : UObject
        {
            var assetBundleName = GetRealAssetPath(abName);

            Util.Log("AssetBundleName:" + assetBundleName);
            if (assetBundleName == null)
            {
                Util.LogError("未找到资源:" + abName);
                //return;

                if (func != null)
                {
                    func.Call();
                    func.Dispose();
                }

                action?.Invoke(null);
                return;
            }

            var request = new LoadAssetRequest();
            request.AssetType = typeof(T);
            request.AssetNames = new[] { abName };
            request.LuaFunc = func;
            request.SharpFunc = action;

            if (!_mLoadRequests.TryGetValue(assetBundleName, out var requests))
            {
                requests = new List<LoadAssetRequest> { request };
                _mLoadRequests.Add(assetBundleName, requests);
                StartCoroutine(OnLoadAssetBundle<T>(assetBundleName));
            }
            else
            {
                requests.Add(request);
            }
        }


        IEnumerator OnLoadAssetBundle<T>(string abName) where T : UObject
        {
            Util.Log("OnLoadAssetBundle new:" + abName);
            var bundleInfo = GetLoadedAssetBundle(abName);
            if (bundleInfo == null)
            {
                yield return StartCoroutine(OnLoadAssetBundle(abName, typeof(T)));
                bundleInfo = GetLoadedAssetBundle(abName);
                if (bundleInfo == null)
                {
                    Util.LogError("OnLoadAsset--->>>" + abName);
                    yield break;
                }
            }

            if (!_mLoadRequests.TryGetValue(abName, out var list))
            {
                _mLoadRequests.Remove(abName);
                yield break;
            }

            foreach (var t in list)
            {
                var ab = bundleInfo.MAssetBundle;
                var names = abName.Split('/');
                var name = names[names.Length - 1];
                name = Path.GetFileNameWithoutExtension(name);
                //ABName1 = ABName1.ToLower();
                //Util.Log(name);

                var obj = ab.LoadAsset(name, t.AssetType);

                if (obj == null)
                {
                    var objs = ab.LoadAllAssets();
                    Util.LogError("LoadAsset error:" + name);
                }
                if (t.SharpFunc != null)
                {
                    t.SharpFunc(new UObject[] { obj });
                    t.SharpFunc = null;
                }
                if (t.LuaFunc != null)
                {
                    t.LuaFunc.Call((object)obj);
                    t.LuaFunc.Dispose();
                    t.LuaFunc = null;
                }
                bundleInfo.MReferencedCount++;
            }
            _mLoadRequests.Remove(abName);
        }


        void LoadAssetBundlefui(string abName, Action<AssetBundle> action = null, LuaFunction func = null)
        {
            var assetBundleName = GetRealAssetPath(abName);
            //Util.Log("LoadAssetBundlefuifuifuifuifui:" + AssetBundleName);
            if (assetBundleName == null)
            {
                Util.LogError("未找到资源:" + abName);
                //return;

                if (func != null)
                {
                    func.Call();
                    func.Dispose();
                }

                action?.Invoke(null);
                return;
            }

            //Util.Log("StartCoroutine:" + AssetBundleName);
            var dataPath = Util.GetDataPath();
            var resPath = Util.AppContentPath(); //游戏包资源目录
            var dataURL = dataPath + assetBundleName;
            var resURL = resPath + assetBundleName;

            //先读取dataPath下面的更新资源
            if (Util.UIPackageResLog > 0) Debug.Log("[LoadFGUI][ResourceManager.LoadFUIPrefab] " + resURL);

            if (File.Exists(dataURL))
            {
                var bundle = AssetBundle.LoadFromFile(dataURL);
                if (bundle != null)
                {
                    action?.Invoke(bundle);
                }
            }
            else
            {
                var bundle = AssetBundle.LoadFromFile(resURL);
                if (bundle != null)
                {
                    action?.Invoke(bundle);
                }
            }
            return;


            LoadAssetRequest request = new LoadAssetRequest();
            request.AssetType = typeof(AssetBundle);
            request.AssetNames = new string[] { abName };
            request.LuaFunc = func;
            request.BundleFunc = action;

            List<LoadAssetRequest> requests = null;
            if (!_mLoadRequests.TryGetValue(assetBundleName, out requests))
            {
                requests = new List<LoadAssetRequest>();
                requests.Add(request);
                _mLoadRequests.Add(assetBundleName, requests);


                //StartCoroutine(OnLoadAssfuietBundlefui(AssetBundleName));
            }
            else
            {
                Util.Log("requests.Add:" + assetBundleName);
                requests.Add(request);
            }
        }


        string GetRealAssetPath(string abName)
        {
            if (abName.Equals(AppConst.AssetDir))
            {
                return abName;
            }
            abName = abName.ToLower();
            if (!abName.EndsWith(AppConst.ExtName))
            {
                abName += AppConst.ExtName;
            }
            if (abName.Contains("/"))
            {
                return abName;
            }
            //string[] paths = m_AssetBundleManifest.GetAllAssetBundles();  产生GC，需要缓存结果
            string tmp_ab_name = "/" + abName;
            foreach (var t in _mAllManifest)
            {
                //var index = t.LastIndexOf('/');
                //var path = t.Remove(0, index + 1);    //字符串操作函数都会产生GC
                //if (path.Equals(abName)) {
                //    return t;
                //}
                if (t.Contains(tmp_ab_name))
                {
                    return t;
                }
            }

            return null;
        }

        IEnumerator OnLoadAssetBundle(string abName, Type type)
        {
            // Util.Log("OnLoadAssetBundleggggggggggggggggggg:" + abName);
            if (mAssetBundleManifest != null)
            {
                var dependencies = mAssetBundleManifest.GetAllDependencies(abName);
                if (dependencies.Length > 0)
                {
                    //Util.Log("dependencies:" + dependencies.Length);
                    _mDependencies.Add(abName, dependencies);
                    foreach (var depName in dependencies)
                    {
                        if (_mLoadedAssetBundles.TryGetValue(depName, out var bundleInfo))
                        {
                            bundleInfo.MReferencedCount++;
                        }
                        else if (!_mLoadRequests.ContainsKey(depName))
                        {
                            if (_isDownLoadingAbName.IndexOf(depName) >= 0) continue;
                            _isDownLoadingAbName.Add(depName);
                            yield return StartCoroutine(OnLoadAssetBundle(depName, type));
                            //Util.Log("=============dependencies:" + depName + " type:" + type);
                            if (_isDownLoadingAbName.IndexOf(depName) >= 0)
                                _isDownLoadingAbName.Remove(depName);
                        }
                    }
                }
            }

            var bundleName = Path.GetFileNameWithoutExtension(abName);
            //LoadAssetBundleFromFileAsync(bundleName, abName, m_LoadedAssetBundles);
            var bundle = LoadAssetBundleFromFile(bundleName, abName);
            if (bundle != null)
            {
                //Util.Log("m_LoadedAssetBundles:" + abName);
                _mLoadedAssetBundles.Add(abName, new AssetBundleInfo(bundle));
            }
        }

        AssetBundleInfo GetLoadedAssetBundle(string abName)
        {
            _mLoadedAssetBundles.TryGetValue(abName, out var bundle);
            if (bundle == null)
            {
                //Util.LogError("未找到资源:" + abName);
                return null;
            }

            // No dependencies are recorded, only the bundle itself is required.
            if (!_mDependencies.TryGetValue(abName, out var dependencies))
                return bundle;

            // Make sure all dependencies are loaded
            foreach (var dependency in dependencies)
            {
                _mLoadedAssetBundles.TryGetValue(dependency, out var dependentBundle);
                if (dependentBundle != null) continue;
                Debug.LogError("can't load assetbundle:" + dependency);
                return null;
            }
            return bundle;
        }

        /// <summary>
        /// 此函数交给外部卸载专用，自己调整是否需要彻底清除AB
        /// </summary>
        /// <param name="abName"></param>
        /// <param name="isThorough"></param>
        public void UnloadAssetBundle(string abName, bool isThorough = false)
        {
            abName = GetRealAssetPath(abName);
            if (abName == null)
                return;
            if (Util.UIPackageResLog > 0) Debug.Log("[LoadFGUI][ResourceManager.UnloadAssetBundle] " + abName + "_" + isThorough);
            UnloadAssetBundleInternal(abName, isThorough);
            UnloadDependencies(abName, isThorough);
            //Debug.Log(m_LoadedAssetBundles.Count + " assetbundle(s) in memory after unloading " + abName);
        }

        void UnloadDependencies(string abName, bool isThorough)
        {
            if (!_mDependencies.TryGetValue(abName, out var dependencies))
                return;

            // Loop dependencies.
            foreach (var dependency in dependencies)
            {
                UnloadAssetBundleInternal(dependency, isThorough);
            }
            _mDependencies.Remove(abName);
        }

        void UnloadAssetBundleInternal(string abName, bool isThorough)
        {
            var bundle = GetLoadedAssetBundle(abName);
            if (bundle == null) return;

            if (--bundle.MReferencedCount > 0) return;
            if (_mLoadRequests.ContainsKey(abName))
            {
                return;     //如果当前AB处于Async Loading过程中，卸载会崩溃，只减去引用计数即可
            }
            bundle.MAssetBundle.Unload(isThorough);
            _mLoadedAssetBundles.Remove(abName);
            Util.Log("AssetBundle UnloadAssetBundleInternal has been unloaded successfully " + abName);
        }

        public IEnumerator DownLoadAssetBundle(string url, string abName, Dictionary<string, AssetBundleInfo> bundlelist)
        {
            using (var request = UnityWebRequestAssetBundle.GetAssetBundle(url))
            {
                yield return request.SendWebRequest();

                if (request.isHttpError || request.isNetworkError)
                {
                    // 下载出错
                    Util.Log(request.error);
                }
                else
                {
                    // Get downloaded asset bundle
                    var bundle = DownloadHandlerAssetBundle.GetContent(request);
                    if (bundle != null)
                    {
                        bundlelist.Add(abName, new AssetBundleInfo(bundle));
                    }

                    // 优先释放request 会降低内存峰值
                    request.Dispose();
                }
            }
        }

        public AssetBundle LoadAssetBundleFromFile(string abName, string filepath)
        {
            Util.Log("LoadAssetBundleFromFile:" + abName);
            var dataPath = Util.GetDataPath();
            var resPath = Util.AppContentPath(); //游戏包资源目录
            filepath = filepath.ToLower();
            var dataURL = dataPath + filepath;
            var resURL = resPath + filepath;

            if(LanguageManager.Instance.language != LanguageType.Chinese)
            {
                //TODO 多语言加载
                string branchpath = LanguageManager.Instance.GetBranchBundlePath(abName);
                if(!string.IsNullOrEmpty(branchpath))
                {
                    string path = "";
                    Util.Log("多语言加载:" + branchpath);
                    Util.Log("dataURL:" + branchpath);
                    var bundle = AssetBundle.LoadFromFile(branchpath);
                    if (bundle != null)
                    {
                        return bundle;
                    }
                }
            }

            //先读取dataPath下面的更新资源
            if (File.Exists(dataURL))
            {
                Util.Log("dataURL:" + dataURL);
                var bundle = AssetBundle.LoadFromFile(dataURL);
                if (bundle != null)
                {
                    return bundle;
                }
                return null;
            }
            else
            {
                Util.Log("resURL:" + resURL);
                var bundle = AssetBundle.LoadFromFile(resURL);
                if (bundle != null)
                {
                    return bundle;
                }
            }
            return null;
        }

        public IEnumerator LoadAssetBundleFromFileAsync(string abName, string filepath, Dictionary<string, AssetBundleInfo> bundlelist)
        {
            if (bundlelist.ContainsKey(abName))
            {
                Util.Log("Bundle Deplicate:" + abName);
                yield return true;
            }
            else
            {

                if (_mLoadAsyncRequests.ContainsKey(abName))
                {
                    if (_mLoadAsyncRequestCount.ContainsKey(abName))
                    {
                        _mLoadAsyncRequestCount[abName]++;
                    }
                    else
                    {
                        _mLoadAsyncRequestCount.Add(abName, 1);
                    }

                    yield return new WaitUntil(() => bundlelist.ContainsKey(abName));

                    if (_mLoadAsyncRequestCount.ContainsKey(abName))
                    {
                        _mLoadAsyncRequestCount[abName]--;
                        if (_mLoadAsyncRequestCount[abName] <= 0)
                        {
                            _mLoadAsyncRequests.Remove(abName);
                        }
                    }
                }
                else
                {
                    var dataPath = Util.GetDataPath();
                    var resPath = Util.AppContentPath(); //游戏包资源目录
                    filepath = filepath.ToLower();
                    var dataURL = dataPath + filepath;
                    var resURL = resPath + filepath;

                    //先读取dataPath下面的更新资源
                    if (File.Exists(dataURL))
                    {
                        Util.Log("dataURL:" + dataURL);
                        var createRequest = AssetBundle.LoadFromFileAsync(dataURL);
                        _mLoadAsyncRequests.Add(abName, createRequest);
                        yield return createRequest;
                        var bundle = createRequest.assetBundle;
                        if (bundle != null && !bundlelist.ContainsKey(abName))
                        {
                            bundlelist.Add(abName, new AssetBundleInfo(bundle));
                            Util.Log("dataPath Bundle Add:" + abName);
                        }
                    }
                    else
                    {
                        Util.Log("resURL:" + resURL);
                        var createRequest = AssetBundle.LoadFromFileAsync(resURL);
                        _mLoadAsyncRequests.Add(abName, createRequest);
                        yield return createRequest;
                        var bundle = createRequest.assetBundle;
                        if (bundle != null && !bundlelist.ContainsKey(abName))
                        {
                            bundlelist.Add(abName, new AssetBundleInfo(bundle));
                            Util.Log("Bundle Add:" + abName);
                        }
                    }
                }
            }
        }

        public void LoadLuaAssetBundleList(List<string> listbundle)
        {
            _mAllManifest = mAssetBundleManifest.GetAllAssetBundles();
            listbundle.AddRange(_mAllManifest.Where(bundleName => bundleName.IndexOf("lua/", StringComparison.Ordinal) >= 0));
        }

        static private void OnAtlasRequest(string name, Action<SpriteAtlas> action)
        {
            //Util.Log("=============" + name);
            name = name.ToLower();
            var rs = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            rs.LoadSpriteAtlasPrefab(name, action);
            return;
        }

        void LoadAssetBundleAsync<T>(string abName, Action<UObject[]> action = null, LuaFunction func = null) where T : UObject
        {
            var pathName = GetRealAssetPath(abName);
            if (pathName == null)
            {
                Util.LogError("未找到资源:" + abName);
                return;
            }
            StartCoroutine(OnLoadAssetBundleAsync<T>(abName, pathName, action, func));
        }

        IEnumerator OnLoadAssetBundleAsync<T>(string abName, string pathName, Action<UObject[]> action = null, LuaFunction func = null) where T : UObject
        {
            // _mLoadedAssetBundlesAsync.Clear();

            var dependencies = mAssetBundleManifest.GetAllDependencies(abName);
            if (dependencies.Length > 0)
            {
                Util.Log("dependencies:" + dependencies.Length);
                foreach (var depName in dependencies)
                {
                    var pathDepName = GetRealAssetPath(depName);

                    if (_mLoadedAssetBundlesAsync.TryGetValue(depName, out _)) continue;
                    Util.Log("dependencies Loaded");
                    yield return LoadAssetBundleFromFileAsync(depName, pathDepName, _mLoadedAssetBundlesAsync);

                    if (_mLoadAsyncRequestCount.ContainsKey(depName))
                    {
                        if (_mLoadAsyncRequestCount[depName] <= 0)
                        {
                            _mLoadAsyncRequests.Remove(depName);
                        }
                    }
                    else
                    {
                        _mLoadAsyncRequests.Remove(depName);
                    }
                }
            }
            else
            {
            }

            yield return LoadAssetBundleFromFileAsync(abName, pathName, _mLoadedAssetBundlesAsync);

            if (_mLoadAsyncRequestCount.ContainsKey(abName))
            {
                if (_mLoadAsyncRequestCount[abName] <= 0)
                {
                    _mLoadAsyncRequests.Remove(abName);
                }
            }
            else
            {
                _mLoadAsyncRequests.Remove(abName);
            }

            _mLoadedAssetBundlesAsync.TryGetValue(abName, out var bundleInfo);
            if (bundleInfo != null)
            {
                var ab = bundleInfo.MAssetBundle;
                var names = abName.Split('/');
                var name = names[names.Length - 1];
                name = Path.GetFileNameWithoutExtension(name);

                var obj = ab.LoadAsset(name);

                action?.Invoke(new[] { obj });
                if (func != null)
                {
                    func.Call((object)obj);
                    func.Dispose();
                }
            }

            /*
            foreach (KeyValuePair<string, AssetBundleInfo> kv in _mLoadedAssetBundlesAsync)
            {
                kv.Value.MAssetBundle.Unload(false);
            }
            _mLoadedAssetBundlesAsync.Clear();
            */
        }

        public static void ClearAllCache()
        {
            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);

            foreach (var info in resManager._mLoadedAssetBundlesAsync.Values)
            {
                info.MAssetBundle.Unload(false);
            }
            foreach (var info in resManager._mLoadedAssetBundles.Values)
            {
                info.MAssetBundle.Unload(false);
            }

            resManager._mLoadedAssetBundlesAsync.Clear();
            resManager._mLoadedAssetBundles.Clear();
            foreach (Sprite sprite in resManager._dSprite.Values)
            {
                if (sprite != null)
                {
                    Destroy(sprite);
                }
            }
            resManager._dSprite.Clear();
            foreach (SpriteAtlas atlas in SLoadedSpriteAtlas.Values)
            {
                if (atlas != null)
                {
                    Destroy(atlas);
                }
            }
            SLoadedSpriteAtlas.Clear();
            foreach (Sprite sprite in SLoadedSprites.Values)
            {
                if (sprite != null)
                {
                    Destroy(sprite);
                }
            }
            SLoadedSprites.Clear();
            foreach (GameObject obj in SLoadedPrefabs.Values)
            {
                if (obj != null)
                {
                    GameObject.DestroyImmediate(obj);
                }
            }
            SLoadedPrefabs.Clear();
            SLoadedAudios.Clear();
            foreach (GameObject obj in SLoadedMaps.Values)
            {
                if (obj != null)
                {
                    GameObject.DestroyImmediate(obj);
                }
            }
            SLoadedMaps.Clear();
            foreach (GameObject obj in SLoadedEffects.Values)
            {
                if (obj != null)
                {
                    GameObject.DestroyImmediate(obj);
                }
            }
            SLoadedEffects.Clear();
            SLoadedSkeletonDataAsset.Clear();
            foreach (Material mat in SLoadedMaterial.Values)
            {
                if (mat != null)
                {
                    GameObject.DestroyImmediate(mat);
                }
            }
            SLoadedMaterial.Clear();
        }
        public static void ClearPrefabCache()
        {
            return;
            /*
            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();

            int index = 0;
            if(prefabRefIndex>= SLoadedPrefabs.Count)
            {
                prefabRefIndex = 0;
            }
            foreach( var prefab in SLoadedPrefabs )
            {
                if( index < prefabRefIndex )
                {
                    index++;
                    continue;
                }
                if( index >= prefabRefIndex + 6 )
                {
                    prefabRefIndex += 6;
                    break;
                }

                index++;
                var prefabRef = prefabRefMap[prefab.Key];
                if(prefabRef != null && Time.realtimeSinceStartup - prefabRef.lastRefTime > 300 )
                {
                    GameObject.DestroyImmediate(prefab.Value,true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(false);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);
                        }
                    }
                }
            }
            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();
            */
        }

        public static bool CheckPrefabExist(string assetName)
        {
            if (!AppConst.BundleMode)
                return true;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);

            assetName = assetName.ToLower();
            var pos = assetName.IndexOf("(clone)");
            if (pos != -1)
            {
                assetName = assetName.Substring(0, pos);
            }

            if (!prefabRefMap.ContainsKey(assetName))
            {
                return false;
            }

            return true;
        }

        public static void DestroyPrefab(string assetName)
        {
            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);

            assetName = assetName.ToLower();
            var pos = assetName.IndexOf("(clone)");
            if (pos != -1)
            {
                assetName = assetName.Substring(0, pos);
            }

            if (!prefabRefMap.ContainsKey(assetName))
            {
                return;
            }

            var prefabRef = prefabRefMap[assetName];
            var prefab = SLoadedPrefabs[assetName];

            if (prefabRef != null && !assetName.StartsWith("model/role") && !assetName.StartsWith("prefabs/skill"))
            {
                prefabRef.refCount--;

                if (prefabRef.refCount <= 0)
                {
                    GameObject.DestroyImmediate(prefab, true);

                    var names = assetName.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }

                    SLoadedPrefabs.Remove(assetName);
                    prefabRefMap.Remove(assetName);
                }
            }
        }


        public static void ClearRoleCache(string[] res,int num)
        {
            if (!AppConst.BundleMode)
                return;

            foreach(string name in res)
            {
                if (prefabRefMap.ContainsKey(name.ToLower()))
                {
                    var prefabRef = prefabRefMap[name.ToLower()];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                    }
                }
            }

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();
            Dictionary<string, float> lihuis = new Dictionary<string, float>();
            List<string> deleteLihuis = new List<string>();
            float deleteTime = 0;

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefab.Key.StartsWith("model/role") && Time.realtimeSinceStartup - prefabRef.lastRefTime > 2)
                {
                    if (lihuis.Count < num)
                    {
                        lihuis.Add(prefab.Key, prefabRef.lastRefTime);
                        if (deleteTime < 0.0001 || deleteTime > prefabRef.lastRefTime)
                        {
                            deleteTime = prefabRef.lastRefTime;
                        }
                    }
                    else
                    {
                        if (deleteTime < prefabRef.lastRefTime)
                        {
                            float tempTime = deleteTime;
                            string deleteKey = "";
                            deleteTime = prefabRef.lastRefTime;
                            foreach (var lihui in lihuis)
                            {
                                if (deleteTime > lihui.Value)
                                {
                                    deleteTime = lihui.Value;
                                }
                                if (Math.Abs(lihui.Value - tempTime) < 0.0001f)
                                {
                                    deleteKey = lihui.Key;
                                    deleteLihuis.Add(lihui.Key);
                                }
                            }

                            if (lihuis.ContainsKey(deleteKey))
                            {
                                lihuis.Remove(deleteKey);
                                lihuis.Add(prefab.Key, prefabRef.lastRefTime);
                            }
                        }
                        else
                        {
                            deleteLihuis.Remove(prefab.Key);
                        }
                    }
                }
            }

            foreach (string lihui in deleteLihuis)
            {
                var prefab = SLoadedPrefabs[lihui];
                var prefabRef = prefabRefMap[lihui];
                if (prefabRef != null && prefab != null)
                {
                    GameObject.DestroyImmediate(prefab, true);
                    deletes.Add(lihui);

                    var names = lihui.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();
            lihuis.Clear();
        }

        public static void ClearLihuiCache(string[] res)
        {
            if (!AppConst.BundleMode)
                return;

            foreach (string name in res)
            {
                if (prefabRefMap.ContainsKey(name.ToLower()))
                {
                    var prefabRef = prefabRefMap[name.ToLower()];
                    if (prefabRef != null)
                    {
                        prefabRef.lastRefTime = Time.realtimeSinceStartup;
                    }
                }
            }

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();
            List<string> deleteLihuis = new List<string>();

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefab.Key.StartsWith("model/drawing") && Time.realtimeSinceStartup - prefabRef.lastRefTime > 2)
                {
                    deleteLihuis.Add(prefab.Key);
                }
            }

            foreach (string lihui in deleteLihuis)
            {
                var prefab = SLoadedPrefabs[lihui];
                var prefabRef = prefabRefMap[lihui];
                if (prefabRef != null && prefab != null)
                {
                    GameObject.DestroyImmediate(prefab, true);
                    deletes.Add(lihui);

                    var names = lihui.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();
        }

        public static void ClearLihuiCache(int num)
        {
            Util.Log("Begin Release Lihui1");
            if (!AppConst.BundleMode)
                return;

            Util.Log("Begin Release Lihui2");

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();
            Dictionary<string, float> lihuis = new Dictionary<string, float>();
            List<string> deleteLihuis = new List<string>();
            float deleteTime = 0;

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefab.Key.StartsWith("model/drawing"))
                {
                    if (lihuis.Count < num)
                    {
                        lihuis.Add(prefab.Key, prefabRef.lastRefTime);
                        if (deleteTime < 0.0001 || deleteTime > prefabRef.lastRefTime)
                        {
                            deleteTime = prefabRef.lastRefTime;
                        }
                    }
                    else
                    {
                        if (deleteTime < prefabRef.lastRefTime)
                        {
                            float tempTime = deleteTime;
                            string deleteKey = "";
                            deleteTime = prefabRef.lastRefTime;
                            foreach (var lihui in lihuis)
                            {
                                if (deleteTime > lihui.Value)
                                {
                                    deleteTime = lihui.Value;
                                }
                                if (Math.Abs(lihui.Value - tempTime) < 0.0001f)
                                {
                                    deleteKey = lihui.Key;
                                    deleteLihuis.Add(lihui.Key);
                                }
                            }

                            if (lihuis.ContainsKey(deleteKey))
                            {
                                lihuis.Remove(deleteKey);
                                lihuis.Add(prefab.Key, prefabRef.lastRefTime);
                            }
                        }
                        else
                        {
                            deleteLihuis.Add(prefab.Key);
                        }
                    }
                }
            }

            foreach (string lihui in deleteLihuis)
            {
                var prefab = SLoadedPrefabs[lihui];
                var prefabRef = prefabRefMap[lihui];
                if (prefabRef != null && prefab != null)
                {
                    GameObject.DestroyImmediate(prefab, true);
                    deletes.Add(lihui);

                    var names = lihui.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }

            Util.Log("Release Lihui Num:" + deleteLihuis.Count);
            Util.Log("Actually Release Lihui Num:" + deletes.Count);
            deletes.Clear();
            lihuis.Clear();
        }

        public static void ClearResOnBattleEnd()
        {
            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefabRef.refCount == 0 && (prefab.Key.StartsWith("model/drawing") || prefab.Key.StartsWith("prefabs/skill") || prefab.Key.StartsWith("model/role")))
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }
            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();

            foreach (var prefab in SLoadedMaps)
            {
                var prefabRef = mapRefMap[prefab.Key];
                if (prefabRef != null && prefabRef.refCount == 0)//&& Time.realtimeSinceStartup - prefabRef.lastRefTime > 200)
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedMaps.Remove(del);
                mapRefMap.Remove(del);
            }
            deletes.Clear();
        }

        public static void ClearSingleLihui(string assetName)
        {
            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);

            assetName = assetName.ToLower();
            var pos = assetName.IndexOf("(clone)");
            if (pos != -1)
            {
                assetName = assetName.Substring(0, pos);
            }

            if (!prefabRefMap.ContainsKey(assetName))
            {
                return;
            }

            var prefabRef = prefabRefMap[assetName];
            var prefab = SLoadedPrefabs[assetName];
            if (prefabRef != null && assetName.StartsWith("model/drawing"))
            {
                GameObject.DestroyImmediate(prefab, true);

                var names = assetName.Split('/');
                var abName = names[names.Length - 1];
                abName = abName.ToLower();

                var abName2 = resManager.GetRealAssetPath(abName);
                Util.Log("prepare remove prefab:" + abName + " " + abName2);

                if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                {
                    var asset = resManager._mLoadedAssetBundlesAsync[abName];
                    if (asset != null)
                    {
                        if (asset.MAssetBundle != null)
                            asset.MAssetBundle.Unload(true);
                        asset = null;
                        resManager._mLoadedAssetBundlesAsync.Remove(abName);

                        Util.Log("remove bundle async:" + abName);
                    }
                }
                else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                {
                    var asset = resManager._mLoadedAssetBundles[abName2];
                    if (asset != null)
                    {
                        if (asset.MAssetBundle != null)
                            asset.MAssetBundle.Unload(true);
                        asset = null;
                        resManager._mLoadedAssetBundles.Remove(abName2);

                        Util.Log("remove bundle:" + abName2);
                    }
                }

                SLoadedPrefabs.Remove(assetName);
                prefabRefMap.Remove(assetName);
            }
        }

        public static void ClearLihui()
        {
            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();

            foreach (var prefab in SLoadedPrefabs)
            {
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefab.Key.StartsWith("model/drawing"))
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }
            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();
        }

        public static void ClearEffectCache()
        {
            foreach (List<GameObject> graphics in skeletonGraphicMap.Values)
            {
                for (int i = 0; i < graphics.Count; i++)
                {
                    GameObject.Destroy(graphics[i]);
                    graphics[i] = null;
                }
                graphics.Clear();
            }

            skeletonGraphicMap.Clear();

            if (!AppConst.BundleMode)
                return;

            var resManager = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource);
            List<string> deletes = new List<string>();

            int index = 0;
            if (prefabRefIndex >= SLoadedPrefabs.Count - 20)
            {
                prefabRefIndex = 0;
            }

            foreach (var prefab in SLoadedPrefabs)
            {
                /*
                if (index < prefabRefIndex)
                {
                    index++;
                    continue;
                }
                if (index >= prefabRefIndex + 20)
                {
                    prefabRefIndex += 20;
                    break;
                }
                index++;
                */
                var prefabRef = prefabRefMap[prefab.Key];
                if (prefabRef != null && prefabRef.refCount == 0 && (prefab.Key.StartsWith("model/drawing") || prefab.Key.StartsWith("prefabs/skill") || prefab.Key.StartsWith("model/role")))
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);
                    Util.Log("prepare remove prefab:" + abName + " " + abName2);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);

                            Util.Log("remove bundle async:" + abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);

                            Util.Log("remove bundle:" + abName2);
                        }
                    }
                }
            }
            foreach (var del in deletes)
            {
                SLoadedPrefabs.Remove(del);
                prefabRefMap.Remove(del);
            }
            deletes.Clear();

            /*
            index = 0;
            if (effectRefIndex >= SLoadedEffects.Count)
            {
                effectRefIndex = 0;
            }

            foreach (var prefab in SLoadedEffects)
            {
                if (index < effectRefIndex)
                {
                    index++;
                    continue;
                }
                if (index >= effectRefIndex + 20)
                {
                    effectRefIndex += 20;
                    break;
                }
                index++;
                var prefabRef = effectRefMap[prefab.Key];
                if (prefabRef != null && Time.realtimeSinceStartup - prefabRef.lastRefTime > 300)
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(false);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);
                        }
                    }
                }
            }
            foreach (var del in deletes)
            {
                SLoadedEffects.Remove(del);
                effectRefMap.Remove(del);
            }
            deletes.Clear();
            */

            index = 0;
            if (mapRefIndex >= SLoadedMaps.Count)
            {
                mapRefIndex = 0;
            }


            foreach (var prefab in SLoadedMaps)
            {
                /*
                if (index < mapRefIndex)
                {
                    index++;
                    continue;
                }
                if (index >= mapRefIndex + 20)
                {
                    mapRefIndex += 20;
                    break;
                }
                index++;
                */
                var prefabRef = mapRefMap[prefab.Key];
                if (prefabRef != null && prefabRef.refCount == 0)//&& Time.realtimeSinceStartup - prefabRef.lastRefTime > 200)
                {
                    GameObject.DestroyImmediate(prefab.Value, true);
                    deletes.Add(prefab.Key);

                    var names = prefab.Key.Split('/');
                    var abName = names[names.Length - 1];
                    abName = abName.ToLower();

                    var abName2 = resManager.GetRealAssetPath(abName);

                    if (resManager._mLoadedAssetBundlesAsync.ContainsKey(abName))
                    {
                        var asset = resManager._mLoadedAssetBundlesAsync[abName];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundlesAsync.Remove(abName);
                        }
                    }
                    else if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                    {
                        var asset = resManager._mLoadedAssetBundles[abName2];
                        if (asset != null)
                        {
                            if (asset.MAssetBundle != null)
                                asset.MAssetBundle.Unload(true);
                            asset = null;
                            resManager._mLoadedAssetBundles.Remove(abName2);
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedMaps.Remove(del);
                mapRefMap.Remove(del);
            }
            deletes.Clear();

            /*
            foreach (var prefab in SLoadedSprites)
            {
                if (spriteRefMap.ContainsKey(prefab.Key))
                {
                    var spriteRef = spriteRefMap[prefab.Key];
                    if (spriteRef != null && Time.realtimeSinceStartup - spriteRef.lastRefTime > 100 &&  spriteRef.refCount == 0 && prefab.Key.IndexOf("00_common_frame_tc_") == -1)
                    {
                        GameObject.DestroyImmediate(prefab.Value, true);
                        deletes.Add(prefab.Key);

                        var names = prefab.Key.Split('/');
                        var abName = names[names.Length - 1];
                        abName = abName.ToLower();

                        var abName2 = resManager.GetRealAssetPath(abName);

                        if (resManager._mLoadedAssetBundles.ContainsKey(abName2))
                        {
                            var asset = resManager._mLoadedAssetBundles[abName2];
                            if (asset != null)
                            {
                                if (asset.MAssetBundle != null)
                                    asset.MAssetBundle.Unload(false);
                                asset = null;
                                resManager._mLoadedAssetBundles.Remove(abName2);
                            }
                        }
                    }
                }
            }

            foreach (var del in deletes)
            {
                SLoadedSprites.Remove(del);
                spriteRefMap.Remove(del);
            }
            deletes.Clear();
            */
        }
    }
}
